/**
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 *   
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 */
package org.jiopi.ibean.kernel.config;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.jiopi.ibean.kernel.util.AnnotationParser;
import org.jiopi.ibean.share.ShareUtil.IOUtil;

/**
 * 
 * 
 * data model of a blueprint's annotations
 * 
 * @since 2010.5.12
 *
 */
public class BlueprintAnnotations {
	private String name;
	private String version;
	private String versionInterface;
	public HashMap<String,Interface> interfaces = new HashMap<String,Interface>();
	/**
	 * store the constructor configurations
	 */
	public HashMap<String,String> constructors = new HashMap<String,String>();
	
	
	private BlueprintAnnotations(){
	}
	
	public String getName() {
		return name;
	}
	
	public String getVersion() {
		return version;
	}

	public String getVersionInterface() {
		return versionInterface;
	}
	
	public Interface getInterface(String name) {
		return interfaces.get(name);
	}
	
	public static BlueprintAnnotations createBlueprintAnnotationsFromJar(File jarFile) throws DocumentException{
		ByteArrayOutputStream out = null;
		ByteArrayInputStream in = null;
		try{
			out = new ByteArrayOutputStream();
			AnnotationParser.parseJarFile(jarFile, out, true, true);
			in = new ByteArrayInputStream(out.toByteArray());
			return createBlueprintAnnotations(in);
		}finally{
			IOUtil.close(out);
			IOUtil.close(in);
		}
		
	}


	public static BlueprintAnnotations createBlueprintAnnotations(File blueprintXmlFile) throws FileNotFoundException, DocumentException{
		InputStream is = null;
		try{
			is = new BufferedInputStream(new FileInputStream(blueprintXmlFile));
			return createBlueprintAnnotations(is);
		}finally{
			IOUtil.close(is);
		}
	}
	
	@SuppressWarnings("unchecked")
	public static BlueprintAnnotations createBlueprintAnnotations(InputStream is) throws DocumentException{
		SAXReader reader = new SAXReader();
		Document doc = reader.read(is);
		BlueprintAnnotations ba = new BlueprintAnnotations();
		Element blueprintElement = doc.getRootElement();
		ba.name = blueprintElement.attributeValue("name");
		ba.version = blueprintElement.attributeValue("version");
		
		Element versionInterfaceElement = blueprintElement.element("version-interface");
		ba.versionInterface = versionInterfaceElement.getTextTrim();
		
		Iterator<Element> interfaceElements = blueprintElement.elementIterator("interface");
		if(interfaceElements!=null){
			while(interfaceElements.hasNext()){
				Element interfaceElement = interfaceElements.next();
				String interfaceClassName = interfaceElement.attributeValue("class");
				Interface interfaceConfig = new Interface();
				ba.interfaces.put(interfaceClassName, interfaceConfig);
				
				Element registerControlpanelElement = interfaceElement.element("register-controlpanel");
				if(registerControlpanelElement!=null){
					interfaceConfig.registerControlpanel = registerControlpanelElement.getTextTrim();
				}
				
				Iterator<Element> registerVariableElements = interfaceElement.elementIterator("register-variable");
				if(registerVariableElements!=null){
					while(registerVariableElements.hasNext()){
						Element registerVariableElement = registerVariableElements.next();
						interfaceConfig.registerVariable.put(registerVariableElement.attributeValue("variable"), registerVariableElement.getTextTrim());
					}
				}
				
				
				Iterator<Element> registerMethods = interfaceElement.elementIterator("register-method");
				if(registerMethods!=null){
					while(registerMethods.hasNext()){
						Element registerMethod = registerMethods.next();
						interfaceConfig.registerMethod.put(registerMethod.attributeValue("method"), registerMethod.getTextTrim());
					}
				}
				
				
				Iterator<Element> sockets = interfaceElement.elementIterator("socket");
				if(sockets!=null){
					while(sockets.hasNext()){
						Element socket = sockets.next();
						interfaceConfig.sockets.add(socket.getTextTrim());
					}
				}
			}
		}
		
		
		Iterator<Element> constructorElements = blueprintElement.elementIterator("constructor");
		if(constructorElements!=null){
			while(constructorElements.hasNext()){
				Element constructor = constructorElements.next();
				Element constructControlpanel = constructor.element("construct-controlpanel");
				ba.constructors.put(constructor.attributeValue("class"), constructControlpanel.getTextTrim());
			}
		}
		
		return ba;
	}
	
	public static class Interface{
		public String registerControlpanel = "";
		public HashMap<String,String> registerMethod = new HashMap<String,String>();
		public HashMap<String,String> registerVariable = new HashMap<String,String>();
		public HashSet<String> sockets = new HashSet<String>();
	}
}
